#include "./myTools.hpp"
//#define USE_AUX

#ifdef USE_AUX
#include<GL/glaux.h>
#endif // USE_AUX

#ifndef USE_AUX
#include"./SOIL.h"
#define USE_SOIL
#endif // USE_AUX

const int CHAR_LEN = 100;
//const char *main_dir = "./";
//char dir_in_file[CHAR_LEN], dir_out_file[CHAR_LEN];
char dir_in_file[] = "luweiqi.txt";

extern database_mt DataBase;
void get1( std::ifstream& );
void get2( std::ifstream& );
void get3( std::ifstream& );
void get4( std::ifstream& );
void get5( std::ifstream& );
void get6( std::ifstream& );
void movePointer( std::ifstream&, int, int& );

/*
 *weight 按格式说明中的顺序1，2，3，4，5返回每个数据单位所占行数
 */
int weight( int type ) {
    int r = 0;
    switch( type ) {
    case 1:
        r = 1;
        break;
    case 2:
        r = 6;
        break;
    case 3:
        ;
    case 4:
        ;
    case 5:
        ;
    case 6:
        r = 1;
        break;
    default:
        ;
    }
    return r;
}

/*
 * 将所有的数据读入，存入结构体中
*/
void mygetData( void ) {
    using namespace std;
    //strcpy( dir_in_file, main_dir );
    //strcat( dir_in_file, "luweiqi.txt" );
    ifstream ifile( dir_in_file, ios_base::in );
    movePointer( ifile, 1, DataBase.Num_detailfile );
    get1( ifile );
    movePointer( ifile, 2, DataBase.Num_material );
    get2( ifile );
    movePointer( ifile, 3, DataBase.Num_vertex );
    get3( ifile );
    movePointer( ifile, 4, DataBase.Num_chartlet );
    get4( ifile );
    movePointer( ifile, 5, DataBase.Num_normal );
    get5( ifile );
    movePointer( ifile, 6, DataBase.Num_submodel );
    get6( ifile );
    ifile.close();
    return;
}

//纹理文件
void get1( std::ifstream& infile ) {
    using namespace std;
    int n = DataBase.Num_detailfile;
    DataBase.DetailFile_Set = new detail_file_mt[n];
    for( int i = 0; i < n; i++ ) {
        DataBase.DetailFile_Set[i] = new char[CHAR_LEN];
        infile.getline( DataBase.DetailFile_Set[i], CHAR_LEN );
    }
    return;
}

//材质
void get2( std::ifstream& infile ) {
    using namespace std;
    int n = DataBase.Num_material;
    DataBase.Material_Set = new material_mt[n];
    for( int i = 0; i < n; i++ ) {
        material_mt& t = DataBase.Material_Set[i];
        infile >> t.ambient[0] >> t.ambient[1] >> t.ambient[2] >> t.ambient[3];
        infile >> t.diffuse[0] >> t.diffuse[1] >> t.diffuse[2] >> t.diffuse[3];
        infile >> t.specular[0] >> t.specular[1] >> t.specular[2] >> t.specular[3];
        infile >> t.emission[0] >> t.emission[1] >> t.emission[2] >> t.emission[3];
        infile >> t.shininess;
        infile >> t.index;
        t.texture = i + 1;
    }
    return;
}

//顶点坐标
void get3( std::ifstream& infile ) {
    int n = DataBase.Num_vertex;
    DataBase.Vertex_Set = new vertex_coordinate_mt[n];
    for( int i = 0; i < n; i++ ) {
        DataBase.Vertex_Set[i] = new GLfloat[3];
        vertex_coordinate_mt& t = DataBase.Vertex_Set[i];
        infile >> t[0] >> t[1] >> t[2];
    }
    return;
}

//贴图坐标
void get4( std::ifstream& infile ) {
    int n = DataBase.Num_chartlet;
    DataBase.Chartlet_Set = new chartlet_coordinate_mt[n];
    for( int i = 0; i < n; i++ ) {
        DataBase.Chartlet_Set[i] = new GLfloat[2];
        chartlet_coordinate_mt& t = DataBase.Chartlet_Set[i];
        infile >> t[0] >> t[1];
    }
    return;
}
void get5( std::ifstream& infile ) {
    int n = DataBase.Num_normal;
    DataBase.Normal_Dirc_Set = new normal_coordinate_mt[n];
    for( int i = 0; i < n; i++ ) {
        DataBase.Normal_Dirc_Set[i] = new GLfloat[3];
        normal_coordinate_mt& t = DataBase.Normal_Dirc_Set[i];
        infile >> t[0] >> t[1] >> t[2];
    }
    return;
}
void get6( std::ifstream& infile ) {
    int n = DataBase.Num_submodel;
    DataBase.Submodel_Set = new submodel_mt[n];
    infile >> DataBase.scale[0] >> DataBase.scale[1] >> DataBase.scale[2];
    for( int i = 0; i < n; i++ ) {
        //DataBase.Submodel_Set[i] = new submodel_mt;
        submodel_mt& t = DataBase.Submodel_Set[i];
        infile >> t.triangleNumber >> t.materialIndex;
        int m = t.triangleNumber;
        t.triangles = new submodel_triangle_mt[m];
        for( int j = 0; j < m; j++ ) {
            t.triangles[j] = new unsigned int[9];
            submodel_triangle_mt& s = t.triangles[j];
            for( int k = 0; k < 9; k++ ) {
                infile >> s[k];
            }// for k
        }// for j
    }// for i
    return;
}

//将文件指针移动到指定类型的数据
void movePointer( std::ifstream& infile, int type, int& Num ) {
    using namespace std;
    int n = 0, c = 0, tem;
    stringstream ss;
    string str;
    infile.seekg( 0L, std::ios::beg );
    while( !infile.eof() ) {
        getline( infile, str );
        if( n == 0 ) {
            ss.clear();
            ss.str( str );
            ss >> tem;
            c += 1;
            n = tem * weight( c );
        }//if
        else
            n -= 1;
        if( c == type )
            break;
    }
    Num = n / weight( type );
    return;
}

void loadTextureFile( void ) {
    int fileIndex;
    material_mt *mat = nullptr;
#ifdef USE_AUX
    AUX_RGBImageRec *Image;
#endif // USE_AUX
#ifdef USE_SOIL
    //unsigned char* Image;
    //int w, h;
#endif // USE_SOIL
    char filename[CHAR_LEN] = {'\0'};
    for( int i = 0; i < DataBase.Num_material; i++ ) {
        mat = &( DataBase.Material_Set[i] );
        fileIndex = mat->index - 1;
        //strcpy( filename, main_dir );
        strcpy( filename, DataBase.DetailFile_Set[fileIndex] );
        //strcat( filename, DataBase.DetailFile_Set[fileIndex] );
        glGenTextures( 1, &( mat->texture ) );
#ifdef USE_AUX
        Image = auxDIBImageLoad( filename );
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, Image->sizeX, Image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, Image->data );
#endif // USE_AUX
#ifdef USE_SOIL
        //mat->texture = SOIL_load_OGL_texture( filename, SOIL_LOAD_RGBA,SOIL_CREATE_NEW_ID,SOIL_FLAG_INVERT_Y );
        mat->texture = SOIL_load_OGL_texture( filename, SOIL_LOAD_RGBA, SOIL_CREATE_NEW_ID, SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA );
        //glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, Image );
#endif // USE_SOIL
        glBindTexture( GL_TEXTURE_2D, mat->texture );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
#ifdef USE_AUX
        if( Image ) {
            if( Image->data )
                delete [] Image->data;
            delete Image;
        }
#endif // USE_AUX
#ifdef USE_SOIL
        //if( Image )
        //    delete Image;
#endif // USE_SOIL
        glBindTexture( GL_TEXTURE_2D, 0 );
    }
}
